/*
 * Project Beknyou
 * Copyright (c) 2010-2011 Saint Paul College, All Rights Reserved
 * Redistributions in source code form must reproduce the above
 * Copyright and this condition.
 * The contents of this file are subject to the GNU General Public
 * License, Version 2 (the "License"); you may not use this file
 * except in compliance with the License. A copy of the License is
 * available at http://www.opensource.org/licenses/gpl-license.php.
 */
package com.benkyou.client.systems;

import com.benkyou.client.GameClient;
import com.benkyou.client.systems.AnimationSystem.anim;
import com.benkyou.common.Player;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.Vector3f;

/**
 *
 * @author Austin Allman
 */
public class AvatarControlSystem implements ActionListener {

    private GameClient gameClient;
    private InputManager inputManager;
    private boolean mainPlayer = false;
    private boolean updateNeeded;
    private DefaultCamSystem camSys;
    private Vector3f walkDirection;
    private Player player;
    private boolean left = false, right = false, up = false, down = false, run = false;

    /**
     * 
     * @param gameClient
     * @param player
     */
    public AvatarControlSystem(GameClient gameClient, Player player) {
        this.gameClient = gameClient;
        this.player = player;
        camSys = gameClient.getCamSys();
        walkDirection = new Vector3f();
        inputManager = gameClient.getInputManager();
        updateNeeded = false;
        mainPlayer = false;
    }

    /**
     * 
     * @return
     */
    public boolean setAsMainPlayer() {
        mainPlayer = true;
        setupKeys();
        return mainPlayer;
    }

    /**
     * 
     * @return
     */
    public boolean isMainPlayer() {
        return mainPlayer;
    }

    /**
     * 
     * @return
     */
    public boolean isUpdateNeeded() {
        return updateNeeded;
    }
    public void setUpdateNeeded(boolean updateNeeded){
        this.updateNeeded = updateNeeded;
    }

    /**
     * 
     */
    public void markForUpdate() {
        updateNeeded = true;
    }

    /**
     * 
     * @param direction
     */
    public void moveCharacter(Vector3f direction, float tpf) {
        direction = direction.normalizeLocal();
        direction.multLocal(tpf);
        if(player.isPhysicsSetup()){
        player.getCharacterPhysics().setWalkDirection(direction.mult(5f));
        
        if (direction.getX() != 0f  && direction.getZ() != 0f) {
            if(isMainPlayer()){
            player.getCharacterPhysics().setViewDirection(direction.negate());
            }else{
                player.getCharacterPhysics().setViewDirection(direction.negate());
            }
            
           walk();
       }else{
        stopWalking();
        }
        
        }
    }

    public void onAction(String binding, boolean isPressed, float tpf) {
        player.getAvatarControlSystem().setUpdateNeeded(true);
        if (binding.equalsIgnoreCase("Sit")) {
            if (isPressed) {
                player.getAnimationSystem().animate(anim.SitOnGround);
            }
        } else if (binding.equalsIgnoreCase("Run")) {
            if (isPressed) {
                run = run ? false : true;

            }
        } else if (binding.equals("Turn Left")) {
            if (isPressed) {

                walk();
                left = true;
            } else {
                left = false;
                stopWalking();
            }
        } else if (binding.equals("Turn Right")) {
            if (isPressed) {

                walk();
                right = true;
            } else {

                right = false;
                stopWalking();
            }
        } else if (binding.equals("Forward")) {
            if (isPressed) {

                walk();
                up = true;
            } else {

                up = false;
                stopWalking();
            }
        } else if (binding.equals("Backwards")) {
            if (isPressed) {
                walk();
                down = true;
            } else {
                down = false;
                stopWalking();
            }
        } else if(binding.endsWith("FirstPerson")){
            if(isPressed){
            gameClient.getCamSys().toggleFPV();
            }
        }

    }

    private void setupKeys() {
        inputManager.addMapping("Turn Left", new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("Turn Right", new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_UP));
        inputManager.addMapping("Backwards", new KeyTrigger(KeyInput.KEY_DOWN));
        //inputManager.addMapping("Sit", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("FirstPerson", new KeyTrigger(KeyInput.KEY_F));
        inputManager.addMapping("Run", new KeyTrigger(KeyInput.KEY_R));
        inputManager.addListener(this, "FirstPerson");
        inputManager.addListener(this, "Run");
        inputManager.addListener(this, "Turn Left");
        inputManager.addListener(this, "Turn Right");
        inputManager.addListener(this, "Forward");
        inputManager.addListener(this, "Backwards");
        inputManager.addListener(this, "Sit");

    }

    private void walk() {
        if (!run) {
            player.getAnimationSystem().animate(anim.Walk);
        } else {
            player.getAnimationSystem().animate(anim.Run);
        }
    }

    private void stopWalking() {
        if (!left && !right && !up && !down) {
            player.getAnimationSystem().animate(anim.Stand);
        }
    }

    /**
     * @return the left
     */
    public boolean isLeft() {
        return left;
    }

    /**
     * @return the right
     */
    public boolean isRight() {
        return right;
    }

    /**
     * @return the up
     */
    public boolean isUp() {
        return up;
    }

    /**
     * @return the down
     */
    public boolean isDown() {
        return down;
    }

    /**
     * 
     * @return
     */
    public boolean isRun() {
        return run;
    }
}
